#pragma once
namespace graph_virtual
{
   namespace details
   {

   }
struct virtual_vertex_iterator_t;
struct virtual_edge_iterator_t;
struct virtual_adj_edges_iterator_t;
struct virtual_adj_vertices_iterator_t;

struct virtual_vertex_iterator_t: std::forward_iterator_tag
{
   void operator ++ ();
   graph_basic::vertex_t& operator * ();
   graph_basic::vertex_t const & operator * () const;
   bool is_empty() const;
private:
   virtual_vertex_iterator_t(virtual_graph_ptr_t graph);
   virtual_graph_t::bucket_list_t::iterator bucket_it_;
   virtual_graph_t::bucket_list_t::iterator bucket_end_;
   graph_basic::vertex_iterator_pair_t graph_it_pair_;
   virtual_graph_ptr_t virtual_graph_;
   graph_basic::graph_ptr_t current_graph_; //needed to keep the graph in memory unless it was unloaded by virtual_graph
   friend virtual_vertex_iterator_t vertices(virtual_graph_ptr_t g);
};

struct virtual_edge_iterator_t: std::forward_iterator_tag
{
   void operator ++ ();
   graph_basic::edge_t const operator * () const;
   graph_basic::edge_t operator * ();
   bool is_empty() const;
private:
   virtual_edge_iterator_t(virtual_graph_ptr_t graph);
   virtual_graph_ptr_t virtual_graph_;
   graph_basic::graph_ptr_t current_graph_; //needed to keep the graph in memory unless it was unloaded by virtual_graph
   virtual_graph_t::bucket_list_t::iterator bucket_it_;
   virtual_graph_t::bucket_list_t::iterator bucket_end_;
   graph_basic::edge_iterator_pair_t cur_graph_edge_it_pair_;
   friend virtual_edge_iterator_t edges(virtual_graph_ptr_t g);
};

struct virtual_adjacent_vertices_iterator_t: std::forward_iterator_tag
{
   void operator ++ ();
   graph_basic::vertex_t& operator * ();
   graph_basic::vertex_t const & operator * () const;
   bool is_empty() const;
private:
   virtual_adjacent_vertices_iterator_t(graph_basic::vertex_id_t v_id, virtual_graph_t* g);
   graph_basic::adj_vertices_iterator_pair_t adj_vert_it_pair_;
   virtual_graph_t* virtual_graph_;
   graph_basic::graph_ptr_t source_graph_; //needed to keep the graph in memory unless it was unloaded by virtual_graph
   friend inline virtual_adjacent_vertices_iterator_t adjacent_vertices(graph_basic::vertex_id_t id, virtual_graph_ptr_t g);
};

struct virtual_adjacent_edges_iterator_t
{
   void operator ++ ();
   graph_basic::edge_t operator * ();
   graph_basic::edge_t const operator * () const;
   bool is_empty() const;
private:
   virtual_adjacent_edges_iterator_t(graph_basic::vertex_id_t v_id, virtual_graph_t* g);
   graph_basic::adj_edges_iterator_pair_t adj_edges_it_pair_;
   virtual_graph_t* virtual_graph_;
   graph_basic::graph_ptr_t source_graph_; //needed to keep the graph in memory unless it was unloaded by virtual_graph
   friend inline virtual_adjacent_edges_iterator_t adjacent_edges(graph_basic::vertex_id_t id, virtual_graph_ptr_t g);
   
};






inline virtual_vertex_iterator_t vertices(virtual_graph_ptr_t g);
inline virtual_edge_iterator_t edges(virtual_graph_ptr_t g);
inline virtual_adjacent_vertices_iterator_t adjacent_vertices(graph_basic::vertex_id_t id, virtual_graph_ptr_t g);
inline virtual_adjacent_edges_iterator_t adjacent_edges(graph_basic::vertex_id_t id, virtual_graph_ptr_t g);

template<>
struct graph_traits<virtual_graph_t>
{
   typedef virtual_vertex_iterator_t vertex_iterator;
   typedef virtual_edge_iterator_t edge_iterator;
   typedef virtual_adj_vertices_iterator_t adj_vertices_iterator;
   typedef virtual_adj_edges_iterator_t adj_edges_iterator;
};
   
}